/**
 * Copyright (c) 2017-2024 Nop Platform. All rights reserved.
 * Author: canonical_entropy@163.com
 * Blog:   https://www.zhihu.com/people/canonical-entropy
 * Gitee:  https://gitee.com/canonical-entropy/nop-entropy
 * Github: https://github.com/entropy-cloud/nop-entropy
 */
package com.gitee.wsl.struct.table

import com.gitee.wsl.api.IFreezable
import com.gitee.wsl.func.Function
import com.gitee.wsl.func.predicate.Predicate
import com.gitee.wsl.struct.table.utils.TableImpls

interface IRowView : IFreezable {

    val id: String?

    val styleId: String?

    val height: Double?

    val isHidden: Boolean

    val table: ITableView?

    val rowIndex: Int
        get() {
            return table?.rows?.indexOf(this)?:-1
        }

    /**
     * 整行所占据的列数
     *
     * @return
     */
    val colCount: Int

    val isEmpty: Boolean
        /**
         * 是否没有任何单元格。对应于getCells().isEmpty()
         */
        get() = cells.isEmpty()

    /**
     * 返回指定位置处的单元格，可能是null或者ProxyCell。
     *
     * @param colIndex 从0开始的单元格index
     */
    fun getCell(colIndex: Int): ICellView?

    fun getRealCell(colIndex: Int): ICellView? {
        val cell: ICellView? = getCell(colIndex)
        if (cell == null || cell.isProxyCell) return null
        return cell
    }

    /**
     * 返回第n个单元格，每个合并单元格只计数一次。
     *
     * @param index 第几个合并单元格，从0开始
     * @return 未找到时返回null
     */
    fun getMergedCell(index: Int): ICellView? {
        var idx = 0
        var i = 0
        val n = cells.size
        while (i < n) {
            val icell = cells[i]
            if (icell == null) {
                if (idx == index) return icell
                idx++
                i++
                continue
            }

            if (idx == index) return icell
            idx++
            i += icell.mergeAcross
            i++
        }
        return null
    }

    fun getCellValue(colIndex: Int): Any? {
        return getCell(colIndex)?.value
    }

    fun getCellText(colIndex: Int): String? {
        return getCell(colIndex)?.text
    }

    fun iterator(): Iterator<ICellView?> {
        return cells.iterator()
    }

    val firstRealCell: ICellView?
        get() {
            val it: Iterator<ICellView?> = iterator()
            while (it.hasNext()) {
                val cell: ICellView? = it.next()
                if (cell != null && !cell.isProxyCell) return cell
            }
            return null
        }

    val lastRealCell: ICellView?
        get() {
            val cells: List<ICellView?> = cells
            for (i in cells.indices.reversed()) {
                val cell: ICellView? = cells[i]
                if (cell != null && !cell.isProxyCell) return cell
            }
            return null
        }

    fun <E : ICellView> forEachCell(rowIndex: Int, processor: ICellProcessor<E>): ProcessResult {
        val it: Iterator<ICellView?> = this.iterator()
        var colIndex = 0
        while (it.hasNext()) {
            if (processor.process(
                    it.next() as E?,
                    rowIndex,
                    colIndex++
                ) == ProcessResult.STOP
            ) return ProcessResult.STOP
        }
        return ProcessResult.CONTINUE
    }

    fun <E : ICellView> forEachRealCell(
        rowIndex: Int,
        processor: ICellProcessor<E>
    ): ProcessResult {
        val it: Iterator<ICellView?> = this.iterator()
        var colIndex = 0
        while (it.hasNext()) {
            val cell = it.next() as E?
            if (cell == null || cell.isProxyCell) {
                colIndex++
                continue
            }

            if (processor.process(
                    cell,
                    rowIndex,
                    colIndex++
                ) == ProcessResult.STOP
            ) return ProcessResult.STOP
        }
        return ProcessResult.CONTINUE
    }

    val cells: List<ICellView?>

    val realCells: List<ICellView>
        get() {
            val cells: MutableList<ICellView> = ArrayList<ICellView>()
            this.cells.forEach { cell: ICellView? ->
                if (cell != null && !cell.isProxyCell) cells.add(cell)
            }
            return cells
        }

    fun findCells(predicate: Predicate<in ICellView?>): List<ICellView?> {
        return cells.filter { predicate.test(it) }
    }

    /**
     * 返回本行中所有非ProxyCell的单元格。
     *
     * @return 返回的集合中可能包含null，但是不包含ProxyCell
     */
    val nonProxyCells: List<ICellView?>
        get() {
            val ret = ArrayList<ICellView?>(colCount)
            for (cell in ret) {
                if (cell == null) {
                    ret.add(cell)
                    continue
                }
                if (cell.isProxyCell) continue
                ret.add(cell)
            }
            return ret
        }

    fun <T> getCellValues(fn: Function<ICellView?, T>): List<T> {
        return TableImpls.getRowCellValues(this, fn)
    }

    val cellValues: List<Any?>
        get() = getCellValues { cell: ICellView? -> cell?.value }

    /**
     * 如果本行的每一个单元格都是空白单元格，则本行为空行
     */
    val isBlankRow: Boolean
        get() {
            for (icell in cells) {
                if (icell == null) continue
                if (!icell.isBlankCell) return false
            }
            return true
        }
}